import random
import re
import json
import jwt
from django.contrib.auth.hashers import make_password
from django.core.paginator import Paginator
from django.http import HttpResponse
from django.shortcuts import render, redirect
from rest_framework.response import Response
from rest_framework.views import APIView
from utils.comm import get_ali_object
from meiduo import settings
from utils.captcha.captcha import captcha
from utils.comm import send_message, get_redis
from .models import *
from .ser import *
import time
import datetime
import random
from django.db import transaction


class NewAPIView(APIView):
    def post(self, request):
        data = NewsSer(data=request.data)
        if data.is_valid():
            data.save()
            return Response({'code': 200, 'msg': '添加成功'})
        else:
            print(data.errors)
            return Response({'code': '10010'})

    def get(self, request):
        news = News.objects.all()
        p = Paginator(news, 2)
        cpage = request.GET.get('page')
        newsR = p.page(cpage)
        ser = NewsSer(newsR, many=True)
        return Response({'code': 200, 'list': ser.data, 'tpage': p.num_pages})


# 注册接口
class Register(APIView):
    def post(self, request):
        username = request.data.get('username')
        # 验证用户名是否为空
        if not username:
            return Response({'code': '10010', 'msg': '用户名不能为空'})
        # 格式是否正确
        name = re.match('\w{5,10}$', username)
        if not name:
            return Response({'code': '10011'})
        # 是否唯一
        user = User.objects.filter(username=username).first()
        if user:
            return Response({'code': '10012'})
        # 验证密码是否为空
        password = request.data.get('password')
        if not password:
            return Response({'code': '10013', 'msg': '密码不能为空'})
        # 密码格式是否正确
        pd = re.match('\w{8,20}$', password)
        if not pd:
            return Response({'msg': '密码格式不对', 'code': '10014'})
        # 手机号
        mobile = request.data.get('mobile')
        # 验证用户名是否为空
        if not mobile:
            return Response({'code': '10015', 'msg': '手机号不能为空'})
        # 格式是否正确
        phone = re.match('^1[3-9]\d{9}$', mobile)
        if not phone:
            return Response({'code': '10016'})
        # 是否唯一
        sloe = User.objects.filter(mobile=mobile).first()
        if sloe:
            return Response({'code': '10017'})
        # 验证码验证newcode，redis取根据手机号
        smscode = request.data.get('smscode')
        conn = get_redis()
        code = conn.get(mobile)
        if code:
            code = str(code, encoding='utf8')
        if smscode != code:
            return Response({'code': '10018'})
        # 判断是否同意协议
        agree = request.data.get('agree')
        if not agree:
            return Response({'code': '10019'})
        # 注册功能
        request.data['password'] = make_password(request.data.get('password'))
        ser = UserSer(data=request.data)
        if ser.is_valid():
            ser.save()
            token = jwt.encode({'data': {'username': username}},
                               settings.SECRET_KEY, algorithm='HS256')

            return Response({'code': 200, 'token': token})

        return Response({'code': 200, 'msg': '注册成功'})


class AddressAPIView(APIView):
    def post(self, request):
        ser = AddressSer(data=request.data)
        if ser.is_valid():
            ser.save()
        return Response({'code': 200})


class Test(APIView):
    def get(self, request):
        # send_message('18530561795', '123', 1)
        get_redis()
        return Response('ok')


class SendSms(APIView):
    def post(self, request):
        mobile = request.data.get('mobile')
        # 验证图片验证码，通过后发信息
        uid = request.data.get('uid')
        imgcode = request.data.get('imgcode')
        conn = get_redis()
        imagecode = conn.get(uid)
        if imagecode:
            imagecode = str(imagecode, encoding='utf8')
            if imgcode.lower() == imagecode.lower():
                codesms = random.randint(1000, 9999)
                res = send_message(mobile, str(codesms), 1)
                print(codesms)
                code = 10010
                if res:
                    code = 200
                    conn = get_redis()
                    conn.setex(mobile, 60, codesms)
                return Response({'code': code})
        return Response({'code': 20020})


class CreateCaptcha(APIView):
    def get(self, request):
        uuid = request.GET.get('uuid')
        name, text, img = captcha.generate_captcha()
        conn = get_redis()
        conn.set(uuid, text)
        return HttpResponse(img, content_type='image/jpg')


class AreaM(APIView):
    def get(self, request):
        pid = request.data.get('pid')
        if not pid:
            areas = Area.objects.filter(parent_id__isnull=True).all()
        else:
            areas = Area.objects.filter(parent_id=pid).all()
        ser = AreaSer(areas, many=True)
        return Response({'code': 200, 'list': ser.data})


def xTree(datas):
    list = []
    tree = {}
    for i in datas:
        tree[i['id']] = i

    for i in datas:
        parent = i['parent']
        if not parent:
            list.append(i)
        else:
            if 'son' not in tree[parent]:
                tree[parent]['son'] = []
            tree[parent]['son'].append(i)
    return list


# 读取首页三级分类
class Home(APIView):
    def get(self, request):
        # 读取一级
        cates = Category.objects.filter(parent_id__isnull=True).all()
        list = []
        for i in cates:
            dict = {}
            dict['id'] = i.id
            dict['name'] = i.name
            # 读取二级
            two = i.subs.all()
            twolist = []
            # 遍历二级获取三级
            for j in two:
                twodict = {}
                twodict['id'] = j.id
                twodict['name'] = j.name
                three = j.subs.all()
                ser = CateSer(three, many=True)
                twodict['subs'] = ser.data
                twolist.append(twodict)

            dict['subs'] = twolist
            list.append(dict)
            # 查询一级分类，一级下面的二级，一级下面的三级，一级下面所有的商品
            categoods = []
            for j in cates:
                dict = {}
                dict['id'] = j.id
                dict['name'] = j.name
                dict['pic'] = str(j.pic)
                two = j.subs.all()
                twoser = CateSer(two, many=True)
                dict['two'] = twoser.data
                # 获取三级
                three = Category.objects.filter(top_parent=j.id, level=3).all()
                threeser = CateSer(three, many=True)
                dict['three'] = threeser.data
                # 获取商品,排序，新品按时间倒序排，价格，销量
                sorted = request.GET.get('sorted')
                topid = request.GET.get('topid')

                goods = Goods.objects.filter(category1_id=j.id, home_show=1).all()
                if sorted:
                    if int(topid) == int(j.id):
                        goods = Goods.objects.filter(category1_id=j.id, home_show=1).order_by('-' + sorted).all()

                gser = GoodsSer(goods, many=True)
                dict['goods'] = gser.data
                categoods.append(dict)
            return Response({"code": 200, 'catelist': list, 'categoods': categoods})


class GoodsM(APIView):
    def get(self, request):
        id = request.GET.get('id')
        good = Goods.objects.filter(id=id).first()
        ser = GoodsSer(good)
        return Response({"code": 200, 'good': ser.data})


class CartM(APIView):
    def post(self, request):
        # 判断此用户是否购买过此商品
        userid = request.data.get('user')
        goodsid = request.data.get('goods')
        number = int(request.data.get('number'))
        cart = Cart.objects.filter(user_id=userid, goods_id=goodsid).first()
        if cart:
            # 如果买过数量+
            cart.number += number
            cart.save()
            return Response({"code": 200})
        else:
            # 没买过购物车新增一条记录
            ser = CartSer(data=request.data)
            if ser.is_valid():
                ser.save()
                return Response({"code": 200})
            else:
                print(ser.errors)
                return Response({"code": 10010})

    def get(self, request):
        userid = request.GET.get('userid')
        cart = Cart.objects.filter(user_id=userid).all()
        ser = ShowCartSer(cart, many=True)
        # 全选
        selected_all = True
        total = 0
        select_total = 0
        select_money = 0
        for i in cart:
            total += i.number
            if i.is_checked == False:
                selected_all = False
            else:
                select_total += i.number
                goods = Goods.objects.filter(id=i.goods_id).first()
                select_money += i.number * float(goods.price)

        return Response(
            {"code": 200, 'list': ser.data, 'selected_all': selected_all, 'total': total, 'select_total': select_total,
             'select_money': select_money})

    def put(self, request):
        id = request.GET.get('id')
        cart = Cart.objects.filter(id=id).first()
        if cart.is_checked == True:
            cart.is_checked = False
        else:
            cart.is_checked = True
        cart.save()
        return Response({"code": 200})

    def delete(self, request):
        id = request.GET.get('id')
        Cart.objects.get(id=id).delete()
        return Response({'code': 200})


# 全选
class SelectAll(APIView):
    def put(self, request):
        userid = request.GET.get('userid')
        selected_all = request.GET.get('selected_all')
        if selected_all == 'true':
            Cart.objects.filter(user_id=userid).update(is_checked=True)
        else:
            Cart.objects.filter(user_id=userid).update(is_checked=False)
        return Response({'code': 200})

    def post(self, request):
        id = request.data.get('id')
        type = request.data.get('type')
        count = request.data.get('count')
        cart = Cart.objects.filter(id=id).first()
        if type == 1:
            # 加
            cart.number += 1
        elif type == 2:
            # 减
            # 判断是否>1
            if cart.number > 1:
                cart.number -= 1
        else:
            # 数量更新
            cart.number = int(count)
        cart.save()
        return Response({"code": 200})


class Buy(APIView):
    def post(self, request):
        userid = request.data.get('userid')
        goods_id = request.data.get('goods_id')
        conn = get_redis()
        key = 'cart_' + userid
        cart = conn.hget(key, goods_id)
        if cart:
            conn.hincrby(key, goods_id, 1)
        else:
            conn.hset('cart_' + userid, goods_id, 1)
        return Response('ok')

    def get(self, request):
        userid = request.GET.get('userid')
        conn = get_redis()
        key = 'cart_' + str(userid)
        carts = conn.hgetall(key)
        data = ''
        list = []
        sum = 0
        tmoney = 0
        t_count = 0
        selected_all = True
        if carts:

            selectedlist = conn.smembers('select_cart_%userid' % int(userid))

            for k, v in carts.items():
                sum += int(v)
                goods = Goods.objects.filter(id=k).first()

                dict = {}
                dict['id'] = goods.id
                dict['name'] = goods.name
                dict['price'] = goods.price
                dict['image'] = 'http://localhost:8000/upload/' + str(goods.pic)
                dict['count'] = v
                if k in selectedlist:
                    tmoney += int(v) * goods.price
                    dict['selected'] = True
                    t_count += int(v)
                else:
                    dict['selected'] = False
                    selected_all = False
                list.append(dict)

        return Response({"code": 200, 'carts': list, 'total': sum, 'tmoney': tmoney, 't_count': t_count,
                         'selected_all': selected_all})


class SelectAll1(APIView):
    def get(self, request):
        conn = get_redis()
        selected = request.GET.get('selected')
        userid = request.GET.get('userid')
        key = 'cart_' + str(userid)
        carts = conn.hgetall(key)

        if selected == 'false':
            conn.srem('select_cart_%userid' % int(userid), *carts.keys())
        else:
            conn.sadd('select_cart_%userid' % int(userid), *carts.keys())
        return Response({'code': 200})

    def post(self, request):
        conn = get_redis()
        selected = request.data.get('flag')
        userid = request.data.get('userid')
        id = request.data.get('id')

        key = 'cart_' + str(userid)
        carts = conn.hgetall(key)
        print(selected)
        if selected == False:
            conn.srem('select_cart_%userid' % int(userid), id)
        else:
            conn.sadd('select_cart_%userid' % int(userid), id)
        return Response({'code': 200})

    def put(self, request):
        conn = get_redis()
        userid = request.data.get('userid')
        id = request.data.get('id')
        type = request.data.get('type')
        key = 'cart_' + str(userid)
        if type == 1:
            conn.hincrby(key, id, 1)
        elif type == 2:
            count = conn.hget(key, id)
            if int(count) > 1:
                conn.hincrby(key, id, -1)
            else:
                return Response({'code': 400})
        elif type == 3:
            count = int(request.data.get('count'))
            if count > 0:
                conn.hset(key, id, count)
            else:
                return Response({'code': 400})
        return Response({'code': 200})

    # 删除
    def delete(self, request):
        conn = get_redis()
        userid = request.GET.get('userid')
        id = request.GET.get('id')
        print(userid)
        print(id)
        conn.hdel('cart_' + str(userid), id)
        return Response({'code': 200})


class GetCheckedCart(APIView):
    def get(self, request):
        # 获取userid
        userid = request.GET.get('userid')
        # 通过userid,is_checked=true查询
        cart = Cart.objects.filter(user_id=userid, is_checked=True).all()
        ser = ShowCartSer(cart, many=True)
        total = 0
        tmoney = 0
        for i in ser.data:
            # 查询总数量
            total += i['number']
            # 查询总金额
            tmoney += i['number'] * float(i['goods']['price'])
        # 返回结果
        return Response({"code": 200, 'list': ser.data, 'total': total, 'tmoney': tmoney})


# 生成订单接口
class CreateOrders(APIView):
    @transaction.atomic
    def post(self, request):
        # 获取userid
        userid = request.data.get('userid')
        address_id = request.data.get('address_id')
        pay_method = request.data.get('pay_method')
        # 根据userid查询购物车中已经选中的记录
        cart = Cart.objects.filter(user_id=userid, is_checked=True).all()
        cartser = ShowCartSer(cart, many=True)
        # 遍历购物车
        total_amount = 0
        for i in cartser.data:
            total_amount += i['number'] * float(i['goods']['price'])
        # 生成订单号
        order_no = datetime.datetime.strftime(datetime.datetime.now(), '%Y%m%d%H%m%s') + str(userid) + str(
            random.randint(1000, 9999))
        # 查找地址构造地址信息
        add = Address.objects.filter(id=address_id).first()
        addressSer = ShowAddressSer(add)
        address = addressSer.data
        addressStr = address['province'] + ' ' + address['city'] + ' ' + address['area'] + ' ' + address[
            'address'] + ' ' + address['receive'] + ' ' + address['mobile']

        datam = {'order_no': order_no, 'user': userid, 'address': addressStr, 'total_amount': total_amount,
                 'pay_method': pay_method}
        # 创建事务结点
        sid = transaction.savepoint()
        try:
            # 调用序列化器添加订单
            ser = OrderInfoSer(data=datam)
            if ser.is_valid():
                ser.save()
                # 生成订单详情
                for i in cartser.data:
                    detaildata = {'order': order_no, 'goods': i['goods']['id'], 'goodsname': i['goods']['name'],
                                  'images': i['goods']['pic'], 'count': i['number'],
                                  'price': float(i['goods']['price']), 'user': userid}
                    # 调用序列化器添加订单详情
                    dser = OrderDetailSer(data=detaildata)
                    if dser.is_valid():
                        dser.save()
            # 购物车删除已经生成订单的记录
            Cart.objects.filter(user_id=userid, is_checked=True).delete()
            # 提交事务
            transaction.savepoint_commit(sid)
            # 返回结果
            return Response({'code': 200, 'order_no': order_no, 'tmoney': total_amount})
        except:
            # 事务回滚
            transaction.savepoint_rollback(sid)
            return Response({'code': 20010})

    def get(self, request):
        userid = request.GET.get('userid')
        orders = OrderInfo.objects.filter(user_id=userid).all()
        ser = ShowOrderInfoSer(orders, many=True)
        return Response({'code': 200, 'list': ser.data})


class Pay(APIView):
    def get(self, request):
        alipay = get_ali_object()

        # 生成支付的url
        query_params = alipay.direct_pay(
            subject="test",  # 商品简单描述
            out_trade_no="myorder" + str(time.time()),  # 用户购买的商品订单号（每次不一样） 20180301073422891
            total_amount=100,  # 交易金额(单位: 元 保留俩位小数)
        )
        pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params)  # 支付宝网关地址（沙箱应用）
        return redirect(pay_url)


class DetailByOrderno(APIView):
    def get(self, request):
        orderno = request.GET.get('orderno')
        detail = OrderDetail.objects.filter(order_id=orderno).all()
        ser = OrderDetailSer(detail, many=True)
        return Response({'list': ser.data})


class CommentM(APIView):
    def post(self, request):
        ser = CommentSer(data=request.data)
        orderno = request.data.get('orderno')
        gid = request.data.get('goods')
        if ser.is_valid():
            ser.save()
            detail = OrderDetail.objects.filter(order_id=orderno, goods_id=gid).first()
            detail.status = True
            detail.save()
            d1 = OrderDetail.objects.filter(order_id=orderno, status=False).first()
            if not d1:
                info = OrderInfo.objects.filter(order_no=orderno).first()
                info.status = 5
                info.save()
            goods = Goods.objects.filter(id=gid).first()
            goods.comments += 1
            goods.save()
            return Response({'code': 200})
        else:
            return Response({'code': 10024})
